#ifndef ENUMERATION_HPP
#define ENUMERATION_HPP

//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <Rendering/OpenGL.hpp>
#include <Tools/Log.hpp>
#include <string>

namespace Rendering {

	//-------------------------------------------------------------------------
	typedef GLuint TLocation;
	typedef GLuint TRenderingID;
	typedef GLsizeiptr TSize;
	typedef GLenum TEnumeration;
	//-------------------------------------------------------------------------	
	enum RenderingPass {
		SHADOW_PASS=0,
		VIEW_PASS,
		DEBUG_PASS
	};	
	//-------------------------------------------------------------------------	
	enum TextureType {
		SQUARE_TEXTURE=0,
		CUBE_TEXTURE,
		RECTANGULAR_TEXTURE
	};
	//-------------------------------------------------------------------------	
	enum ContextType {
		PUBLIC_CONTEXT=0, 
		PRIVATE_CONTEXT,
		GEOMETRIC_CONTEXT };
	//-------------------------------------------------------------------------	
	enum TargetType { 
		COLOR0_TARGET=0, 
		COLOR1_TARGET, 
		COLOR2_TARGET, 
		DEPTH_TARGET };
	//-------------------------------------------------------------------------	
	enum PixelFormat { 
		PIX_R8G8B8A8=0,
		PIX_R16G16B16A16,
		PIX_R32G32B32A32,
		PIX_L32,
		PIX_DEPTH16,
		PIX_DEPTH24,
		PIX_DEPTH32 };
	//-------------------------------------------------------------------------	
	struct PixelFormatDetail { int internalFormat, format, type, components; };
	//-------------------------------------------------------------------------
	enum VertexBufferType { 
		VERTEX_BUFFER,
		COLOR_BUFFER,
		NORMAL_BUFFER,
		TEXCOORD0_BUFFER,
		TEXCOORD1_BUFFER,
		TEXCOORD2_BUFFER,
		INDEX_BUFFER,
		TANGENT_BUFFER };
	//-------------------------------------------------------------------------	
	struct BufferDetail { int components; TSize size; TEnumeration type; TEnumeration state; };
	//-------------------------------------------------------------------------	
	enum TextureUnit { 
		TEXTURE_UNIT0,
		TEXTURE_UNIT1, 
		TEXTURE_UNIT2,
		TEXTURE_UNIT3,
		TEXTURE_UNIT4 };
	//-------------------------------------------------------------------------
	enum RessourceType { 
		SCALAR_INT, 
		SCALAR_FLOAT, 
		VECTOR_FLOAT2, 
		VECTOR_FLOAT3, 
		VECTOR_FLOAT4, 
		TEXTURE_1D,
		TEXTURE_2D };
	//-------------------------------------------------------------------------					
	enum MeshType { 
		TRIANGLE_MESH, 
		QUAD_MESH };
	//-------------------------------------------------------------------------
	class Enumeration {
	public:		
		// Texture
		static inline TEnumeration GetTextureType(TextureType type);
		// Pixel format
		static inline PixelFormatDetail GetPixelFormatDetails(PixelFormat format);
		static inline TEnumeration GetTextureUnit(TextureUnit unit);
		// Target
		static inline TEnumeration GetTargetType(TargetType type);
		// Buffer
		static inline BufferDetail GetBufferDetail(VertexBufferType type);
		static inline VertexBufferType GetBufferType(const std::string& name);
		static inline std::string GetBufferType(VertexBufferType type);		
		// Mesh
		static inline TEnumeration GetMeshType(MeshType type);
	private:
		static const TEnumeration MeshTypeMapping[];	// Map on MeshType
		static const PixelFormatDetail PixelMapping[];  // Map on PixelFormat
		static const int TextureUnitMapping[]; 			// Map on Texture unit
		static const TEnumeration TargetTypeMapping[];	// Map on TargetType
		static const BufferDetail BufferMapping[];		// Map on BufferType
		static const TEnumeration TextureMapping[];		// Map on Texture map
	};
	//-------------------------------------------------------------------------
	inline TEnumeration Enumeration::GetMeshType(MeshType type) {
		return MeshTypeMapping[type];
	}
	//-------------------------------------------------------------------------
	inline PixelFormatDetail Enumeration::GetPixelFormatDetails(PixelFormat format) {
		return PixelMapping[format];
	}
	//-------------------------------------------------------------------------
	inline TEnumeration Enumeration::GetTextureUnit(TextureUnit unit) {
		return TextureUnitMapping[unit];
	}
	//-------------------------------------------------------------------------
	inline TEnumeration Enumeration::GetTargetType(TargetType type) {
		return TargetTypeMapping[type];
	}	
	//-------------------------------------------------------------------------
	inline BufferDetail Enumeration::GetBufferDetail(VertexBufferType type) {
		return BufferMapping[type];
	}
	//-------------------------------------------------------------------------
	inline VertexBufferType Enumeration::GetBufferType(const std::string& name) {
		if(name.compare("gl_Vertex")==0)
			return VERTEX_BUFFER;
		if(name.compare("gl_MultiTexCoord0")==0)
			return TEXCOORD0_BUFFER;
		if(name.compare("gl_MultiTexCoord1")==0)
			return TEXCOORD1_BUFFER;
		if(name.compare("gl_MultiTexCoord2")==0)
			return TEXCOORD2_BUFFER;
		if(name.compare("gl_Normal")==0)
			return NORMAL_BUFFER;
		if(name.compare("gl_Index")==0)
			return INDEX_BUFFER;
		if(name.compare("gl_Color")==0)
			return COLOR_BUFFER;
		if(name.compare("Tangent")==0)
			return TANGENT_BUFFER;
	}
	//-------------------------------------------------------------------------
	inline std::string Enumeration::GetBufferType(VertexBufferType type) {
		switch(type) {
			case VERTEX_BUFFER	  : return "gl_Vertex";
			case TEXCOORD0_BUFFER : return "gl_MultiTexCoord0";
			case TEXCOORD1_BUFFER : return "gl_MultiTexCoord1";
			case TEXCOORD2_BUFFER : return "gl_MultiTexCoord2";
			case NORMAL_BUFFER	  : return "gl_Normal";
			case INDEX_BUFFER	  : return "gl_Index";
			case COLOR_BUFFER	  : return "gl_Color";			
			case TANGENT_BUFFER	  : return "Tangent";
			default				  : Tools::Error("Enumeration::GetBufferType Buffer type error"); return "Error";
		}
	}
	//-------------------------------------------------------------------------
	inline TEnumeration Enumeration::GetTextureType(TextureType type) {
		return TextureMapping[type];
	}
}


#endif //ENUMERATION_HPP
